﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#pragma once

#include "GcmpGuiMainFrame.h"
#include "IMainWindow.h"
#include "QStatusBar.h"
#include "UIWelcome.h"
#include "GnufTrashBin.h"
#include "QMainWindow"

#include "IMainWindowPrivate.h"          //TODO:


class QMdiArea;
class QMdiSubWindow;
class QTimer;

class GmSubFrame;

namespace gcmp
{
    class IJournalRecordEventReceiver;
    class IJournalReplayEventReceiver;
}
namespace gnuf
{
    class AsynchronousTaskManager;
}
namespace gcmp
{
    class UniIdentity;
    class IUiView;
    class IUiDocument;
    class CommandEvent;
    class CheckDefaultCommandEvent;
    class ApplyOrCancelWidget;
    class IUIWelcome;
    class UIRibbon_Deprecated;
    class UIStatusBar_Deprecated;
    class StatusBarImpl;
    class Ribbon;
    class IApplicationConfig;
    class ApplicationWindowEvent;
    class IDocumentEventHandler;
    class IUIModelessPanelMgr_Deprecated;
    class UiDocumentViewManager;
    class IUiViewEventHandler;
    class IUiDocumentEventHandler;
    class GmJournalApplicationEventHandler;
    class IUiViewLayoutEvent;
    class ISelectionChangeEventHandler;
    class UiViewLayoutManager;
    

    // 主窗口。
    class GCMP_GUI_MAIN_FRAME_EXPORT GmMainWindow 
        : public QMainWindow
        , public IMainWindow
        , public IMainWindowPrivate
        , public gcmp::ITrashBinHandler
    {
        Q_OBJECT
    public:
        GmMainWindow();
        virtual ~GmMainWindow();

        //IMainWindow接口
    public:
        virtual IControlDefinitionLibrary* GetControlDefinitionLibrary() const final;

        virtual IRibbon* GetRibbon() const final;
        virtual IStatusBar* GetStatusBar() const final;

        virtual IApplicationWindowEvent* GetMainWindowEvent() const final;
        virtual UInt64 GmMainWindow::GetApplicationWindowId() const final;
  
        virtual void Show() final;
        virtual void Hide() final;

        virtual void ShowMaximized() final;
        virtual void ShowMinimized() final;
        virtual void ShowFullScreen() final;
        virtual void ShowNormal() final;

        virtual std::wstring GetWindowTitle() const final;
        virtual bool SetWindowTitle(const std::wstring& title) final;

        virtual void SetUiViewDisabled(const std::vector<IUiView*>& vecUiViews, bool bDisable) override;

        // 更新控件的状态。
        virtual void UpdateControlStatus() override;

        // 平铺窗口
        virtual void TileSubWindows() override;
        // 层叠窗口
        virtual void CascadeSubWindows() override;

        virtual bool GetMdiAreaDomain(int& posx, int& posy, int& width, int& height) const;
        //// 发送事件
        //virtual bool SendEvent(OwnerPtr<IExternalEvent> pEvent) override;
        //virtual void PostEvent(OwnerPtr<IExternalEvent> pEvent) override;

        //激活窗口
        virtual void ActivateWindow() override;
        virtual IUiView* CreateOrOpenUiView(int uiDocId, const ElementId& modelViewId, bool isModelViewShared, const std::wstring &tag) override;

        virtual bool SetWindowStyleTheme(WindowStyleTheme styleTheme) override;
        virtual IPlatformUiRefreshedEvent* GetPlatformUiRefreshedEvent() const override;


        // Apply/Cancel
        virtual void ShowApplyOrCancelGui(const std::wstring& hint, const std::wstring& applyCmd, const std::wstring& cancelCmd) override;
        virtual void HideApplyOrCancelGui() override;

        // 初始化
        virtual bool Initialize() override;

        // IMainWindowPrivate接口实现
    public:
        virtual void OnApplyOrCancelProcessed() override;
        virtual void ResetApplyOrCancelGuiPosition() override;
        virtual std::vector<std::shared_ptr<gcmp::ApplyOrCancelWidget> > GetApplyOrCancelGuis() const override { return m_applyOrCancelGuis; }
        virtual bool SetMainWindowHelper(OwnerPtr<IMainWndHelper> pMainWindowHelper) final;

    public:
        virtual void DeleteApplyOrCancelGui(int uiDocId);
        
        // 程序是否正在退出的标志
        virtual bool GetApplicationIsClosing() const { return m_applicationIsClosing; }
        virtual void SetApplicationIsClosing(bool applicationIsClosing) { m_applicationIsClosing = applicationIsClosing; }
  
        QMdiArea* GetQMdiArea() const { return m_pMDIArea; }
        UInt64 GetMdiAreaId() const override; 

        // 临时
        void BuildUi();
   

    protected:
        // 重载基类事件函数。
        virtual bool eventFilter(QObject *object, QEvent *event) override;
        virtual void keyPressEvent(QKeyEvent* pEvent) override;
        virtual void closeEvent(QCloseEvent *event) override;
        //virtual void customEvent(QEvent* event) override;
        virtual void moveEvent(QMoveEvent * pEvent) override;
        virtual bool focusNextPrevChild(bool next) override;
        //修改大小
        void resizeEvent(QResizeEvent *event);

        virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;

    protected:
        void LogCustomAction();

    private slots:
        void OnSubWindowActivated(QMdiSubWindow* pMdiSubWindow, bool bActivatedProgrammactially = false);  //处理UIView激活 
        void OnUIViewClose(QMdiSubWindow * pMdiSubWindow);//处理UIView关闭消息

    private:
        friend class GmSubFrame;

        //关闭主窗口前检查文档状态并挨个询问其是否要关闭(true表示可以继续关闭)
        bool EnquiryDocumentBeforeClose(IUiDocument*);

        //关闭所有View，采用程序关闭的方式，关闭的过程中不会记录独立的LOG
        void closeAllSubWindowsAutomatically();

        // 程序激活SubWindow,激活过程中不会记录gm.view.activated语句
        void ActivateSubWindow(QMdiArea* mDIArea,QMdiSubWindow *subWindow);

        // 获取UiView对应的SubFrame（若未找到，则返回nullptr）
        GmSubFrame* GetCorrespondingSubFrame(IUiView* pUiView) const;

        // 查找当前UIDoc的ApplyOrCancelGui
        std::shared_ptr<ApplyOrCancelWidget> FindCurrentApplyOrCancelGui() const;

    private:
        std::set<IUiView*> m_disableUiViews;//存储需要禁用的uiveiw指针

        QMdiArea*  m_pMDIArea;                // MDI区域。
        bool       m_applicationIsClosing;    // 程序是否正在退出的标志(用于防止激活重入)
        OwnerPtr<IPlatformUiRefreshedEvent>  m_pPlatformUiRefreshedEvent; // 控件刷新事件，什么情况下使用(侧边栏） ？？
       
        mutable OwnerPtr<IRibbon>                   m_pRibbonBar;
        mutable StatusBarImpl*                      m_pStatusBar;
        //OwnerPtr<UIWelcome>                         m_upUIWelcome; //欢迎界面
        OwnerPtr<IApplicationWindowEvent> m_pMainWindowEvent;
        gcmp::OwnerPtr<gnuf::AsynchronousTaskManager > m_asynchronousTaskManager;

        //////////////////////////////////////////////////////////////////////////
        // TODO: 
        // 所有的Apply/Cancel Gui。Gui的实际owner是Parent Gui(QMainWindow)
        std::vector<std::shared_ptr<ApplyOrCancelWidget> > m_applyOrCancelGuis;
        OwnerPtr<IMainWndHelper> m_pMainWindowHelper;
        OwnerPtr<UiViewLayoutManager>        m_opUiViewLayoutManager;
        //////////////////////////////////////////////////////////////////////////
        // TODO: 
        // Gcmp默认处理方式( 编辑模式同步视图、文档关闭同步按钮 )
        OwnerPtr<IUiDocumentEventHandler>       m_pUiDocumentEventHandler; 
        OwnerPtr<ISelectionChangeEventHandler>  m_opUIDocSelectionChangedEventHandler;


        //////////////////////////////////////////////////////////////////////////
        // TODO: 
        // 日志脚本事件接受者
        OwnerPtr<gcmp::IJournalRecordEventReceiver> m_opJournalRecordEventReceiver;// 内部MainWindow专属

        gcmp::OwnerPtr<gcmp::GmJournalApplicationEventHandler> m_pGmJournalApplicationEventHandler;// 内部MainWindow专属

     private:
       gcmp::OwnerPtr< gcmp::TrashBin > m_opTrashBin;
       virtual bool onAllowToClear(const gcmp::TrashBin *) const override
       {
           //// Make sure whether or not allow to clear the trash bin, again. If
           //// not allowed yet, skip this time segment to have a try next time.
           //if (gnuf::Utility::isExecutingCommand())
           //    return false;

           return true;
       }

    };

}//namespace gcmp
